﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Vortex.Debugging {

	class HtmlLogWriter : IDisposable {
		private const int PADDING_LEVEL_PX = 32;
		private readonly string TAB_SNIPPET = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";

		private FileStream _logStream;
		private StreamWriter _logWriter;

		/// <summary>
		/// Initializes a new instance of the <see cref="HtmlLogWriter"/> class.
		/// </summary>
		/// <param name="fileName">Name of the log file.</param>
		/// <param name="append">if set to <c>true</c> then log will be appended to file if it exists.</param>
		public HtmlLogWriter(string fileName, bool append) {
			_logStream = File.Open(fileName, append ? FileMode.OpenOrCreate : FileMode.Create);
			_logWriter = new StreamWriter(_logStream, System.Text.Encoding.UTF8);
			_logWriter.AutoFlush = true;
			WriteHeader();
		}

		#region IDisposable Members

		public void Dispose() {
			WriteFooter();
			_logWriter.Dispose();
			_logStream.Dispose();
		}

		#endregion

		private void WriteHeader() {
			System.Reflection.Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly();
			thisAssembly.GetManifestResourceNames();
			Stream source = thisAssembly.GetManifestResourceStream("Vortex.Debugging.logfile.template");
			StreamReader reader = new StreamReader(source);
			_logWriter.Write(reader.ReadToEnd());
		}

		private void WriteFooter() {
			_logWriter.Write("</body></html>");
		}


		private static readonly string NORMAL_LINE_TEMPLATE = "<div class='row' title='{0}'><div style='padding-left: {2}px;'><span class='msg-{1}'>{3}</span></div></div>";
		private static readonly string DETAILS_LINE_TEMPLATE = "<div class='row' title='{0}'><div style='padding-left: {2}px;'><span class='msg-{1}' onclick='toggleDetails(this);'>[+] Show details<br/></span><span class='msg-{1}' style='display: none;'>{3}</span></div></div>";
		/// <summary>
		/// Writes the log line.
		/// </summary>
		/// <param name="paddingLevel">The padding level.</param>
		/// <param name="severity">The severity of message.</param>
		/// <param name="message">The message text.</param>
		public void WriteLine(int paddingLevel, Severity severity, string message) {
			DateTime time = DateTime.Now;
			message = System.Security.SecurityElement.Escape(message);

			_logWriter.WriteLine(
				severity == Severity.Details ? DETAILS_LINE_TEMPLATE : NORMAL_LINE_TEMPLATE,
				time.ToString("hh:mm:ss.fff @ MMM dd"),
				severity.ToString(),
				paddingLevel * PADDING_LEVEL_PX,
				message.Replace("\n", "<br />\n").Replace("\t", TAB_SNIPPET)
			);

		}
	}

}
